#define SECS_PER_DAY (SECS_PER_HOUR*24L) /* long constant! */
#define HOURS_PER_DAY 24
#define DAYS_PER_WEEK 7
#define DAYS_PER_YEAR 365
#define LEAP_PERIOD (365*4+1)
#define BASE_YEAR 1970
#define UNTIL_1980 (365*10+2) /* 01-01-1970 to 01-01-1980 */
#define UNTIL_FEB29 (365*2+31+29-1) /* 01-01-1970 to 29-02-1972 */
#define UNTIL_2000 (365*30+7+31+28-1) /* 01-01-1970 to 28-02-2000 */
è#define THURSDAY 4
#define APRIL (90-1)
#define OCTOBER (273-1)
/*
Similar structure (struct tm) is defined in <time.h>, but I prefer to use my own - I think it makes code clearer. (And, also, my structure is slightly shorter).
*/ struct date_time {
short yr, /* year */
mo, /* month (0-11) */
dy, /* day */
dw, /* day of week (0-6) */
hr, /* hours */
mn, /* minutes */
sc; /* seconds */
};
typedef int boolean; typedef unsigned short word; typedef unsigned long dword;
struct date_time dt; /* we must fill this structure
and then convert it to string */ dword time; word days; register char *chptr; register word i;
time = *tptr - timezone; /* because C time() function returns GMT value */ days = (word)(time / SECS_PER_DAY); /* days since 1970 */
if (days < UNTIL_1980)
return NULL; /* on dates before 1980, ctime() returns NULL */
/* first, calculating time - it's simple */ time %= SECS_PER_DAY; /* seconds this day */ dt.hr = (word)(time / SECS_PER_HOUR); i = (word)(time % SECS_PER_HOUR); /* seconds this hour */ dt.mn = i / SECS_PER_MIN; dt.sc = i % SECS_PER_MIN;
è/* day of week - it's simple too */ dt.dw = (days + THURSDAY) % DAYS_PER_WEEK;
/* then calculating date - it's little bit more complex */ i = days - UNTIL_FEB29; /* days since Feb 29 1972 */ days -= (i / LEAP_PERIOD + 1); /* delete all Feb 29s */ /* now we can calculate everything as if leap years doesn't exist */
dt.yr = days / DAYS_PER_YEAR + BASE_YEAR; if ((i % LEAP_PERIOD) == 0) { /* today Feb 29th special case */
dt.mo = 1; /* Feb */ dt.dy = 29;
} else {
days %= DAYS_PER_YEAR; /* days this year */ if (
daylight /* if a daylight-saving-time zone is specified */
&& days >= nearest_sunday (
dt.yr>1986 ? APRIL+1 : APRIL+24, dt.yr) && days < nearest_sunday (OCTOBER+25, dt.yr) /* and this day belongs to summer period */ /* (1980-1986: Apr 24 - Oct 25 */ /* after 1986: Apr 1 - Oct 25) */
) {
/* then it's one hour later */ if (++dt.hr == HOURS_PER_DAY) {